#!/usr/bin/perl

use DBI;
use strict;
use Cwd;

print "[main] new_calibration_pipeline_reduction.pl\n\n";

my $dsn="dbi:Pg:dbname=flux_monitoring;host=localhost;port=5432";
my $user="postgres";
my $password="";

# Set up a connection to the database listing the RPFITS files that need to be
# processed.
my $dbh=DBI->connect($dsn,$user,$password,{ RaiseError => 0, AutoCommit => 1});

# Query for all observations from the calibration table
my $toc_query="SELECT * FROM calibration WHERE ".
    "(primary1_processed=FALSE AND primary1_source IS NOT NULL) OR ".
    "(primary2_processed=FALSE AND primary2_source IS NOT NULL) OR ".
    "(primary3_processed=FALSE AND primary3_source IS NOT NULL) OR ".
    "(primary4_processed=FALSE AND primary4_source IS NOT NULL)";

my $toc=$dbh->prepare($toc_query);
$toc->execute;
my %calibration_row;
my @fields=qw(file source project obstime freq_if1 freq_if2
	      primary1_file primary1_source primary1_project primary1_time
	      primary2_file primary2_source primary2_project primary2_time
	      primary3_file primary3_source primary3_project primary3_time
	      primary4_file primary4_source primary4_project primary4_time
	      primary1_processed primary2_processed primary3_processed primary4_processed
	      bandpass_file bandpass_source bandpass_project bandpass_time);

while (@calibration_row{@fields}=$toc->fetchrow()){

    print "[main] found source calibrator file '".$calibration_row{'file'}."'\n\n";

    # begin by determining the actions this script will need to take on this
    # data set
    print "[main] determining necessary actions...\n";
    # we do always need to extract the source file into a miriad dataset
    my $extract_source_required=1;
    my $extract_source_complete=0;
    my $extract_source_deleted=0;
    # need to extract some primary calibrators
    my (@extract_primary_required,@extract_primary_complete,@extract_primary_deleted);
    my @primary_calibration_required;
    my @primary_calibration_complete;
    my @primary_is_planet;
    my @primary_is_available;
    for (my $i=1;$i<=4;$i++){
	if (($calibration_row{"primary$i\_source"} ne "")&&
	    ($calibration_row{"primary$i\_processed"}==0)){
	    $primary_is_available[$i]=1;
	    $extract_primary_required[$i]=1;
	    $extract_primary_complete[$i]=0;
	    $extract_primary_deleted[$i]=0;
	    # is the primary a planet?
	    if (($calibration_row{"primary$i\_source"}!~/[Uu]ranus/)&&
		($calibration_row{"primary$i\_source"}!~/[Mm]ars/)){
		# no, it is not a planet
		$primary_is_planet[$i]=0;
		$primary_calibration_required[$i]=1;
		$primary_calibration_complete[$i]=0;
	    } else {
		# yes, it is a planet
		$primary_is_planet[$i]=1;
		$primary_calibration_required[$i]=0;
	    }
	} else {
	    $extract_primary_required[$i]=0;
	    $primary_calibration_required[$i]=0;
	    $primary_is_available[$i]=0;
	}
    }
    # will we need to extract a bandpass calibrator for the source?
    my $extract_source_bandpass_required=0;
    my $extract_source_bandpass_complete=0;
    my $extract_source_bandpass_deleted=0;
    my $source_is_bandpass=0;
    if ($calibration_row{'bandpass_file'} ne $calibration_row{'file'}){
	# the source can not be used as its own bandpass calibrator
	$extract_source_bandpass_required=1;
    } else {
	# the source can be used as its own bandpass calibrator
	$extract_source_bandpass_required=0;
	$source_is_bandpass=1;
    }
    # calibration required on the source
    my $source_calibration_required=1;
    my $source_calibration_complete=0;
    my $source_bandpass_calibration_required=$extract_source_bandpass_required;
    my $source_bandpass_calibration_complete=0;

    # will we need to extract a bandpass calibrator for the primary?
    my @extract_primary_bandpass_required;
    my @extract_primary_bandpass_complete;
    my @extract_primary_bandpass_deleted;
    my @primary_bandpass_calibration_required;
    my @primary_bandpass_calibration_complete;
    my @primary_is_bandpass;
    my (@pbandpass_file,@pbandpass_source);
    for (my $i=1;$i<=4;$i++){
	if ($primary_is_available[$i]==0){
	    next;
	}
	($pbandpass_file[$i],$pbandpass_source[$i])=
	    &primary_bandpass($calibration_row{"primary$i\_file"},$dbh);
	if ($calibration_row{"primary$i\_file"} ne $pbandpass_file[$i]){
	    # the primary can not be used as its own bandpass calibrator
	    $extract_primary_bandpass_required[$i]=1;
	    $primary_is_bandpass[$i]=0;
	    $primary_bandpass_calibration_required[$i]=1;
	    $primary_bandpass_calibration_complete[$i]=0;
	} else {
	    # the primary can be used as its own bandpass calibrator
	    $extract_primary_bandpass_required[$i]=0;
	    $primary_is_bandpass[$i]=1;
	    $primary_bandpass_calibration_required[$i]=0;
	}
    }

    # now summarise the procedure and do the actions
    print "[main] summary of required actions follows:\n";
    print "[main] miscellaneous data collection:\n";
    print "[main] determine array configuration\n";
    my $array_name;
    print "[main] determining array configuration for source calibrator observations...\n";
    my $gda_query="SELECT array_name FROM array_configurations ".
			  "WHERE start_date<'".$calibration_row{'obstime'}."' ".
			  "AND end_date>'".$calibration_row{'obstime'}."'";
    my $gda=$dbh->prepare($gda_query);
    $gda->execute;
    while (my @arrays=$gda->fetchrow()){
	$array_name=$arrays[0];
	print "[main] array configuration was ".$array_name." during source calibrator observations\n\n";
    }
    $gda->finish;

    print "[main] determine close calibration events\n";
    # when was the last acal,dcal,pcal?
    print "[main] determining times of last calibrators...\n";
    my ($dcal_time,$pcal_time,$acal_time)=
	&get_cal_times($calibration_row{'obstime'},$calibration_row{'freq_if1'},
		       $calibration_row{'freq_if2'},$dbh);
    print "[main]     last delay cal was @ ".$dcal_time."\n";
    print "[main]     last phase cal was @ ".$pcal_time."\n";
    print "[main] last amplitude cal was @ ".$acal_time."\n\n";

    print "\n";
    print "[main] file extractions:\n";
    my ($full_path,$source_path);
    if ($extract_source_required==1){
	print "[main] extract source '".$calibration_row{'file'}."'\n";
	# start by loading the calibrator FITS file into miriad format
	# search for the full path of the file
	($full_path,$source_path)=&attach_path($calibration_row{'file'},$dbh);
	print "[main] convert source calibrator to miriad dataset\n";
	&fits_to_miriad($full_path,$calibration_row{'freq_if1'},
			$calibration_row{'freq_if2'});
	for (my $j=1;$j<=2;$j++){
	    &rename_source($source_path,$calibration_row{'source'},
			   $calibration_row{"freq_if$j"},"source");
	}
	print "[main] source calibrator converted to miriad dataset\n\n";
	$extract_source_complete=1;
    }
    print "[main] get RA & Dec of source\n";
    # the actual RA and Dec of the observation
    print "[main] obtaining RA & Dec of source calibrator...\n";
    my ($observed_ra,$observed_dec)=&get_ra_dec($source_path,
						"source",$calibration_row{'freq_if1'});
    print "[main] source calibrator RA=".$observed_ra." & Dec=".$observed_dec."\n\n";

    my $calibrator_path;
    if ($extract_source_bandpass_required==1){
	print "[main] extract source bandpass '".$calibration_row{'bandpass_file'}."'\n";
	($full_path,$calibrator_path)=&attach_path($calibration_row{'bandpass_file'},$dbh);
	&fits_to_miriad($full_path,$calibration_row{'freq_if1'},
			$calibration_row{'freq_if2'});
	for (my $j=1;$j<=2;$j++){
	    &rename_source($calibrator_path,$calibration_row{'bandpass_source'},
			   $calibration_row{"freq_if$j"},"source_bandpass");
	}
	print "[main] source bandpass calibrator converted to miriad dataset\n\n";
	$extract_source_bandpass_complete=1;
    } else {
	if ($source_is_bandpass==1){
	    print "[main] source file '".$calibration_row{'file'}."' is identified as a ".
		"bandpass source ('".$calibration_row{'bandpass_file'}."')\n";
	}
    }
    my @primary_path;
    my @pbandpass_path;
    for (my $i=1;$i<=4;$i++){
	if ($primary_is_available[$i]==0){
	    next;
	}
	if ($extract_primary_required[$i]==1){
	    print "[main] extract primary $i '".$calibration_row{"primary$i\_file"}."'\n";
	    ($full_path,$primary_path[$i])=&attach_path($calibration_row{"primary$i\_file"},$dbh);
	    &fits_to_miriad($full_path,$calibration_row{'freq_if1'},
			    $calibration_row{'freq_if2'});
	    for (my $j=1;$j<=2;$j++){
		&rename_source($primary_path[$i],$calibration_row{"primary$i\_source"},
			       $calibration_row{"freq_if$j"},"primary$i");
	    }
	    print "[main] primary calibrator converted to miriad dataset\n\n";
	    $extract_primary_complete[$i]=1;
	}
	if ($extract_primary_bandpass_required[$i]==1){
	    print "[main] extract primary $i bandpass '".$pbandpass_file[$i]."'\n";
	    ($full_path,$pbandpass_path[$i])=&attach_path($pbandpass_file[$i],$dbh);
	    &fits_to_miriad($full_path,$calibration_row{'freq_if1'},
			    $calibration_row{'freq_if2'});
	    for (my $j=1;$j<=2;$j++){
		&rename_source($pbandpass_path[$i],$pbandpass_source[$i],
			       $calibration_row{"freq_if$j"},"primary$i\_bandpass");
	    }
	    print "[main] bandpass calibrator for primary calibrator converted to miriad dataset\n\n";
	    $extract_primary_bandpass_complete[$i]=1;
	} else {
	    print "[main] primary $i file '".$calibration_row{"primary$i\_file"}."' is ".
		"identified as a bandpass source ('".$pbandpass_file[$i]."')\n";
	}
    }
    print "\n";
    print "[main] calibration:\n";
    if ($source_bandpass_calibration_required==1){
	print "[main] calibration required on source bandpass\n";
	for (my $j=1;$j<=2;$j++){
	    &calibrate_source($calibrator_path,"source_bandpass",
			      $calibration_row{"freq_if$j"},1);
	}
	print "[main] source bandpass calibration complete\n";
    }
    for (my $i=1;$i<=4;$i++){
	if ($primary_bandpass_calibration_required[$i]==1){
	    print "[main] calibration required on primary $i bandpass\n";
	    for (my $j=1;$j<=2;$j++){
		&calibrate_source($pbandpass_path[$i],"primary$i\_bandpass",
				  $calibration_row{"freq_if$j"},1);
	    }
	    print "[main] primary $i bandpass calibration requires copy to primary $i\n";
	    for (my $j=1;$j<=2;$j++){
		&calibration_copy($pbandpass_path[$i],"primary$i\_bandpass",
				  $calibration_row{"freq_if$j"},$primary_path[$i],
				  "primary$i",$calibration_row{"freq_if$j"});
	    }
	    print "[main] primary $i bandpass calibration complete\n";
	}
	if ($primary_calibration_required[$i]==1){
	    print "[main] calibration required on primary $i\n";
	    if ($primary_is_bandpass[$i]==1){
		print "[main] primary $i calibration will include bandpass calibration\n";
		for (my $j=1;$j<=2;$j++){
		    &calibrate_source($primary_path[$i],"primary$i",
				      $calibration_row{"freq_if$j"},1);
		}
	    } else {
		for (my $j=1;$j<=2;$j++){
		    &calibrate_source($primary_path[$i],"primary$i",
				      $calibration_row{"freq_if$j"},0);
		}
	    }
	    print "[main] primary $i calibration complete\n";
	}
    }
    print "\n";
    print "[main] flux measurement:\n";
    for (my $i=1;$i<=4;$i++){
	my @flux_scale_factor;
	if ($primary_is_available[$i]==0){
	    next;
	}
	if ($source_bandpass_calibration_required==1){
	    print "[main] copy source bandpass to source\n";
	    for (my $j=1;$j<=2;$j++){
		&calibration_copy($calibrator_path,"source_bandpass",
				  $calibration_row{"freq_if$j"},$source_path,
				  "source",$calibration_row{"freq_if$j"});
	    }
	    print "[main] source bandpass copy complete\n";
	}
	if ($source_calibration_required==1){
	    print "[main] calibration required on source\n";
	    if ($source_is_bandpass==1){
		print "[main] source calibration will include bandpass calibration\n";
		for (my $j=1;$j<=2;$j++){
		    &calibrate_source($source_path,"source",
				      $calibration_row{"freq_if$j"},1);
		}
	    } else {
		print "[main] source calibration will exclude bandpass calibration\n";
		for (my $j=1;$j<=2;$j++){
		    &calibrate_source($source_path,"source",
				      $calibration_row{"freq_if$j"},0);
		}
	    }
	    print "[main] source calibration complete\n";
	}
	if ($primary_is_planet[$i]==0){
	    print "[main] scale source flux by primary $i using gpboot\n";
	    for (my $j=1;$j<=2;$j++){
		$flux_scale_factor[$j]=
		    &scale_gpboot($source_path,"source",
				  $calibration_row{"freq_if$j"},
				  $primary_path[$i],"primary$i",
				  $calibration_row{"freq_if$j"});
	    }
	    print "[main] source flux scaling complete\n";
	} else {
	    print "[main] scale source flux by primary $i using mfboot\n";
	    for (my $j=1;$j<=2;$j++){
		$flux_scale_factor[$j]=
		    &scale_mfboot($source_path,"source",
				  $calibration_row{"freq_if$j"},
				  $primary_path[$i],"primary$i",
				  $calibration_row{"primary$i\_source"},
				  $calibration_row{"freq_if$j"});
	    }
	    print "[main] source flux scaling complete\n";
	}
#	print "[main] measure source flux with calred\n";
	print "[main] measure source flux with closure\n";
#	my @scalar_flux;
#	my @vector_flux;
	my @triple_amplitude;
	my @triple_amplitude_scatter;
	for (my $j=1;$j<=2;$j++){
#	    ($scalar_flux[$j],$vector_flux[$j])=
	    ($triple_amplitude[$j],$triple_amplitude_scatter[$j])=
		&measure_flux($source_path,"source",$calibration_row{"freq_if$j"});
	}
	print "[main] measure closure phase with closure\n";
	my @actual_phase;
	my @theoretical_phase;
	for (my $j=1;$j<=2;$j++){
	    ($actual_phase[$j],$theoretical_phase[$j])=
		&measure_closure_phase($source_path,"source",
				       $calibration_row{"freq_if$j"});
	}
	print "[main] get information about last pointing\n";
	my ($lastpoint_time,$lastpoint_source,$lastpoint_az,$lastpoint_el)=
	    &get_pointing_info($calibration_row{'file'},$dbh);
	print "[main] get information about telescope position\n";
	my ($source_az,$source_el)=&get_az_el($source_path,"source",
					      $calibration_row{"freq_if1"});
	my ($primary_az,$primary_el)=&get_az_el($primary_path[$i],"primary$i",
						$calibration_row{"freq_if1"});
	print "[main] enter information into database\n";
	for (my $j=1;$j<=2;$j++){
	    my $enf_query;
	    if ($lastpoint_source ne ""){
		$enf_query="INSERT INTO fluxes VALUES (NEXTVAL('fluxes_entry_num_seq'),'".$calibration_row{'source'}."','".
		    $calibration_row{'obstime'}."','".$calibration_row{'project'}."',".
		    $calibration_row{"freq_if$j"}.",'".$calibration_row{"primary$i\_source"}."','".
		    $calibration_row{"primary$i\_project"}."',TIMESTAMP '".$calibration_row{'obstime'}."'- TIMESTAMP '".
		    $calibration_row{"primary$i\_time"}."',".$i.",'".$observed_ra."','".$observed_dec."','".
		    $array_name."',".$actual_phase[$j].",".$theoretical_phase[$j].",".$flux_scale_factor[$j].",".
#		$scalar_flux[$j].",".$vector_flux[$j].",'".$calibration_row{'bandpass_source'}."','".
		    "'".$calibration_row{'bandpass_source'}."','".
		    $calibration_row{'bandpass_project'}."',TIMESTAMP '".$calibration_row{'obstime'}."'- TIMESTAMP '".
		    $calibration_row{'bandpass_time'}."','".$lastpoint_source."',TIMESTAMP '".$calibration_row{'obstime'}.
		    "'- TIMESTAMP '".$lastpoint_time."',".$lastpoint_az.",".$lastpoint_el.",".$source_az.",".$source_el.",".
		    $primary_az.",".$primary_el.",TIMESTAMP '".$calibration_row{'obstime'}."'- TIMESTAMP '".$acal_time."',".
		    "TIMESTAMP '".$calibration_row{'obstime'}."'- TIMESTAMP '".$pcal_time."',TIMESTAMP '".
		    $calibration_row{'obstime'}."'- TIMESTAMP '".$dcal_time."',".
		    $triple_amplitude[$j].",".$triple_amplitude_scatter[$j].
		    ")";
	    } else {
		$enf_query="INSERT INTO fluxes VALUES (NEXTVAL('fluxes_entry_num_seq'),'".$calibration_row{'source'}."','".
		    $calibration_row{'obstime'}."','".$calibration_row{'project'}."',".
		    $calibration_row{"freq_if$j"}.",'".$calibration_row{"primary$i\_source"}."','".
		    $calibration_row{"primary$i\_project"}."',TIMESTAMP '".$calibration_row{'obstime'}."'- TIMESTAMP '".
		    $calibration_row{"primary$i\_time"}."',".$i.",'".$observed_ra."','".$observed_dec."','".
		    $array_name."',".$actual_phase[$j].",".$theoretical_phase[$j].",".$flux_scale_factor[$j].",".
#		$scalar_flux[$j].",".$vector_flux[$j].",'".$calibration_row{'bandpass_source'}."','".
		    "'".$calibration_row{'bandpass_source'}."','".
		    $calibration_row{'bandpass_project'}."',TIMESTAMP '".$calibration_row{'obstime'}."'- TIMESTAMP '".
		    $calibration_row{'bandpass_time'}."',NULL,NULL,NULL,NULL,".
		    $source_az.",".$source_el.",".
		    $primary_az.",".$primary_el.",TIMESTAMP '".$calibration_row{'obstime'}."'- TIMESTAMP '".$acal_time."',".
		    "TIMESTAMP '".$calibration_row{'obstime'}."'- TIMESTAMP '".$pcal_time."',TIMESTAMP '".
		    $calibration_row{'obstime'}."'- TIMESTAMP '".$dcal_time."',".
		    $triple_amplitude[$j].",".$triple_amplitude_scatter[$j].
		    ")";
	    }		
	    print "[main/debug] executing query $enf_query\n";
	    my $enf=$dbh->prepare($enf_query);
	    $enf->execute;
	    $enf->finish;
	}
	print "[main] set processed flag on primary $i\n";
	my $prp_query="UPDATE calibration SET primary$i\_processed=TRUE WHERE ".
	    "primary$i\_file='".$calibration_row{"primary$i\_file"}."' AND ".
	    "file='".$calibration_row{'file'}."'";
	print "executing query $prp_query\n";
	my $prp=$dbh->prepare($prp_query);
	$prp->execute;
	$prp->finish;
    }
    print "\n";
    print "[main] deleting created files\n";
    if ($extract_source_complete==1){
	print "[main] deleting source file\n";
	&delete_files($calibration_row{'freq_if1'},$calibration_row{'freq_if2'},$source_path,
		      "source");
	$extract_source_complete=0;
    }
    if ($extract_source_bandpass_complete==1){
	print "[main] deleting source bandpass file\n";
	&delete_files($calibration_row{'freq_if1'},$calibration_row{'freq_if2'},$calibrator_path,
		      "source_bandpass");
    }
    for (my $i=1;$i<=4;$i++){
	if ($primary_is_available[$i]==0){
	    next;
	}
	print "[main] deleting primary $i file\n";
	&delete_files($calibration_row{'freq_if1'},$calibration_row{'freq_if2'},$primary_path[$i],
		      "primary$i");
	if ($extract_primary_bandpass_complete[$i]==1){
	    print "[main] deleting primary bandpass file\n";
	    &delete_files($calibration_row{'freq_if1'},$calibration_row{'freq_if2'},$pbandpass_path[$i],
			  "primary$i\_bandpass");
	}
    }
    print "\n";

#    exit;
}

sub delete_files {
    my ($freq1,$freq2,$source_path,$source_name)=@_;

    my $delete_command;

    if ($freq1!=-1){
	$delete_command="rm -rf ".$source_path."/".$source_name.".".$freq1;
	&execute_command($delete_command);
    }
    if ($freq2!=-1){
	$delete_command="rm -rf ".$source_path."/".$source_name.".".$freq2;
	&execute_command($delete_command);
    }
}

sub primary_bandpass {
    my ($primary_file,$dbh)=@_;

    my $gbf_query="SELECT bandpass_file,bandpass_source FROM calibration WHERE file='".$primary_file."'";
#    print "executing $gbf_query\n";
    my $gbf=$dbh->prepare($gbf_query);
    my $nres=$gbf->execute;
    my $bandpass_file;
    my $bandpass_source;
#    print " [primary_bandpass/debug] found $nres possible primary bandpass sources\n";
    if ($nres==1){
	($bandpass_file,$bandpass_source)=$gbf->fetchrow();
#	print " [primary_bandpass/debug] found primary bandpass $bandpass_file ($bandpass_source)\n";
    }
    $gbf->finish;

    return ($bandpass_file,$bandpass_source);
}

sub fits_to_miriad {
    my $full_path=$_[0];
    my $frequency=$_[1];
    my $f2=$_[2];

    my $miriad_command;
    my $options_string="birdie,rfiflag,xycorr";
    $full_path=&shrink_path($full_path);

    # get the base of the filename
    my $filepart=$full_path;
    $filepart=~s/(.*)\.(.*)$/$1/;

    # step 1. ATLOD
    $miriad_command="atlod ";
    $miriad_command.="in=".$full_path." ";
    $miriad_command.="out=".$filepart.".uv ";
    # an aside - check that the outfile doesn't exist
    if (-e $filepart.".uv"){
	# it does exist, remove it
	system "rm -rf $filepart.uv";
    }
    # now we attach options based on frequency
    if ($frequency>15000){
	$options_string.=",opcorr";
    }
    $miriad_command.="options=".$options_string." ";
    # if the frequency is the same for both IFs then we select
    # only the first IF
    if ($frequency==$f2){
	$miriad_command.="ifsel=1 ";
    }

    &execute_command($miriad_command);
    
    # step 2. UVFLAG
#    $miriad_command="uvflag ";
#    $miriad_command.="vis=".$filepart.".uv ";
#    $miriad_command.="flagval=flag ";

#    &execute_command($miriad_command."select=auto");
#    &execute_command($miriad_command."edge=100");
#    # we need to flag out a lot more
#    # channels for RFI contamination
#    my $flagging_command="rfi_flagger.pl --dataset ".
#	$filepart.".uv";
#    &execute_command($flagging_command);

    # step 3. ATFIX (3mm data only)
    if ($frequency>70000){
	$miriad_command="atfix ";
	$miriad_command.="vis=".$filepart.".uv ";
	$miriad_command.="out=".$filepart.".fix.uv ";
	$miriad_command.="tsyscal=any";
	&execute_command($miriad_command);
	&execute_command("rm -rf ".$filepart.".uv");
	&execute_command("mv ".$filepart.".fix.uv ".$filepart.".uv");
    }

    # step 4. UVSPLIT
    $miriad_command="uvsplit ";
    $miriad_command.="vis=".$filepart.".uv ";
    $miriad_command.="options=clobber";

    &execute_command($miriad_command);

    # now we can delete the UV file
    &execute_command("rm -rf ".$filepart.".uv");
}

sub scale_gpboot {
    my ($source_path,$source,$source_freq,$cal_path,$cal,$cal_freq)=@_;
    my $miriad_command;

    $source_path=&shrink_path($source_path);
    $cal_path=&shrink_path($cal_path);
    $miriad_command="gpboot ";
    $miriad_command.="vis=".$source_path."/".$source.".".$source_freq." ";
    $miriad_command.="cal=".$cal_path."/".$cal.".".$cal_freq;

    my @cmd_result;
    my $flux_scale_factor;
    @cmd_result=&execute_command($miriad_command);
    for (my $i=0;$i<=$#cmd_result;$i++){
#	print "GPBOOT output: <$cmd_result[$i]>\n";
	if ($cmd_result[$i]=~/^Secondary flux density scaled by\:/){
	    my @els=split(/\s+/,$cmd_result[$i]);
	    $flux_scale_factor=$els[$#els];
	}
    }
    
    return $flux_scale_factor;
}

sub scale_mfboot {
    my ($source_path,$source,$source_freq,$cal_path,$cal_file,$cal,$cal_freq)=@_;
    my $miriad_command;

    $source_path=&shrink_path($source_path);
    $cal_path=&shrink_path($cal_path);
    $miriad_command="mfboot ";
    $miriad_command.="vis=".$cal_path."/".$cal_file.".".$cal_freq.",".
	$source_path."/".$source.".".$source_freq." ";
    $miriad_command.="\"select=source($cal)\" ";
    $miriad_command.="clip=0.3 device=/null";

    my @cmd_result;
    my $flux_scale_factor;
    @cmd_result=&execute_command($miriad_command);
    for (my $i=0;$i<=$#cmd_result;$i++){
#	print "$cmd_result[$i]\n";
	if ($cmd_result[$i]=~/^Scaling the data by/){
	    my @els=split(/\s+/,$cmd_result[$i]);
	    $flux_scale_factor=$els[$#els];
#	    print "fsf = $flux_scale_factor\n";
	}
    }
    
    return ($flux_scale_factor);
}

sub measure_flux {
    my ($path,$source,$freq)=@_;
    my $miriad_command;

    $path=&shrink_path($path);
#    $miriad_command="calred ";
#    $miriad_command.="vis=".$path."/".$source.".".$freq." ";
#    $miriad_command.="stokes=i ";
#    $miriad_command.="interval=1000";
    $miriad_command="closure ";
    $miriad_command.="vis=".$path."/".$source.".".$freq." ";
    $miriad_command.="stokes=i ";
    $miriad_command.="device=/null ";
    $miriad_command.="options=amplitude ";

    my @cmd_result;
#    my $vector_flux;
#    my $scalar_flux;
    my $triple_amplitude;
    my $triple_amplitude_scatter;
    @cmd_result=&execute_command($miriad_command);
    my $next_line=0;
    for (my $i=0;$i<=$#cmd_result;$i++){
#	if ($next_line==1){
#	    my @els=split(/\s+/,$cmd_result[$i]);
#	    $scalar_flux=$els[1];
#	    $vector_flux=$els[2];
#	    $next_line=0;
#	} elsif ($cmd_result[$i]=~/^Source\s/){
#	    $next_line=1;
#	}
	my @els=split(/\s+/,$cmd_result[$i]);
	if (($els[0] eq "Mean")&&($els[1] eq "amplitude:")){
	    $triple_amplitude=$els[2];
	} elsif (($els[0] eq "Actual")&&($els[3] eq "scatter:")){
	    $triple_amplitude_scatter=$els[4];
	}
    }
#    return ($scalar_flux,$vector_flux);
    return ($triple_amplitude,$triple_amplitude_scatter);
}

sub measure_closure_phase {
    my ($path,$source,$freq)=@_;
    my $miriad_command;

    $path=&shrink_path($path);
    $miriad_command="closure ";
    $miriad_command.="vis=".$path."/".$source.".".$freq." ";
    $miriad_command.="stokes=i ";
    $miriad_command.="device=/null";

    my @cmd_result;
    my $theoretical_phase;
    my $actual_phase;
    @cmd_result=&execute_command($miriad_command);
    for (my $i=0;$i<=$#cmd_result;$i++){
	if ($cmd_result[$i]=~/^Actual\sclosure/){
	    my @els=split(/\s+/,$cmd_result[$i]);
	    $actual_phase=$els[$#els];
	} elsif ($cmd_result[$i]=~/^Theoretical\sclosure/){
	    my @els=split(/\s+/,$cmd_result[$i]);
	    $theoretical_phase=$els[$#els];
	}
    }

    return($actual_phase,$theoretical_phase);
}

sub get_pointing_info {
    my $file_needed=$_[0];
    my $dbh=$_[1];

    my ($got_file,$pointing_time,$pointing_source,$pointing_az,$pointing_el);

    my $gpi_query="SELECT file,last_pointing_time,last_pointing_source,".
	"last_pointing_az,last_pointing_el FROM extracted_files WHERE ".
	"file='".$file_needed."'";
    my $gpi=$dbh->prepare($gpi_query);
    $gpi->execute;
    ($got_file,$pointing_time,$pointing_source,$pointing_az,$pointing_el)=
	$gpi->fetchrow();
    $gpi->finish;
    return ($pointing_time,$pointing_source,$pointing_az,$pointing_el);
}

sub shrink_path {
    my $full_path=$_[0];

    my $currdir=getcwd;
    my @eldir=split(/\/+/,$currdir);
    for (my $i=1;$i<=$#eldir;$i++){
	if ($full_path=~/^\/$eldir[$i].*/){
	    $full_path=~s/^\/$eldir[$i]//;
	} else {
	    $full_path="..".$full_path;
	}
    }
    
    if (($full_path!~/^\/.*\/.*/)&&
	($full_path!~/^\.\.\/.*/)){
	$full_path=".".$full_path;
    }

    return $full_path;
}

sub execute_command {
    my $command_to_execute=$_[0];
    
    print "  [execute_command] executing command <".$command_to_execute.">\n";
    my @cmnd_result;
    open(CMND,"-|")||exec $command_to_execute;
    while(<CMND>){
	chomp;
	my $line=$_;
	push @cmnd_result,$line;
    }
    close(CMND);

    return @cmnd_result;
}

sub get_az_el {
    my ($path,$source,$freq)=@_;
    my $miriad_command;
    my $varlogfile="vars.log";

    $path=&shrink_path($path);
    $miriad_command="uvlist ";
    $miriad_command.="vis=".$path."/".$source.".".$freq;
    $miriad_command.=" options=var,full ";
    $miriad_command.="log=".$varlogfile;

    &execute_command("rm -f ".$varlogfile);
    &execute_command($miriad_command);

    open(VARS,$varlogfile);
    my $observed_az;
    my $observed_el;
    while(<VARS>){
	chomp;
	my @els=split(/\s+/);
	for (my $i=0;$i<=$#els;$i++){
	    if ($els[$i] eq "antaz"){
		$observed_az=$els[$i+2];
	    } elsif ($els[$i] eq "antel"){
		$observed_el=$els[$i+2];
	    }
	}
    }
    close(VARS);

    &execute_command("rm -f ".$varlogfile);

    return ($observed_az,$observed_el);
}

sub get_cal_times {
    my ($source_time,$freq1,$freq2,$dbh)=@_;
    
    my ($dcal_time,$pcal_time,$acal_time);
    
    for (my $i=0;$i<3;$i++){
	my $ctg_query="SELECT * FROM events WHERE event_time<'".$source_time."' ".
	    "AND (if1_freq=".$freq1." AND if2_freq=".$freq2.") AND ";
	if ($i==0){
	    print " [get_cal_times/debug] searching for delay cal events...\n";
	    $ctg_query.="(event_type='dcal') ";
	} elsif ($i==1){
	    print " [get_cal_times/debug] searching for phase cal events...\n";
	    $ctg_query.="(event_type='pcal') ";
	} elsif ($i==2){
	    print " [get_cal_times/debug] searching for amplitude cal events...\n";
	    $ctg_query.="(event_type='acal' OR event_type='paddle') ";
	}
	$ctg_query.="ORDER BY event_time DESC LIMIT 1";
	my $ctg=$dbh->prepare($ctg_query);
	my $ngot=$ctg->execute;
	if ($ngot==1){
	    my @els=$ctg->fetchrow();
	    if ($i==0){
		$dcal_time=$els[1];
		print " [get_cal_times/debug] time: $dcal_time\n";
	    } elsif ($i==1){
		$pcal_time=$els[1];
		print " [get_cal_times/debug] time: $pcal_time\n";
	    } elsif ($i==2){
		$acal_time=$els[1];
		print " [get_cal_times/debug] time: $acal_time\n";
	    }
	}
	$ctg->finish;
    }

    return ($dcal_time,$pcal_time,$acal_time);
}

sub rename_source {
    my ($path,$source_name,$frequency,$type)=@_;
    
    my $rename_command="mv ";
    $rename_command .= $path."/".$source_name.".".$frequency." ";
    $rename_command .= $path."/".$type.".".$frequency;

    execute_command($rename_command);

}

sub attach_path {
    my $file_needed=$_[0];
    my $dbh=$_[1];
    
    my $full_path;
    my $path_only;
    
    my $gef=$dbh->prepare("SELECT file,path FROM extracted_files WHERE ".
			  "file='".$file_needed."'");
    $gef->execute;
    while (my ($extracted_file,$extracted_path)=$gef->fetchrow()){
	$full_path=$extracted_path."/".$extracted_file;
	$path_only=$extracted_path;
    }
    $gef->finish;
    return ($full_path,$path_only);
}

sub get_ra_dec {
    my ($path,$source,$freq)=@_;
    my $miriad_command;

    $path=&shrink_path($path);
    $miriad_command="uvindex ";
    $miriad_command.="vis=".$path."/".$source.".".$freq;
    
    my @cmd_result;
    my $observed_ra;
    my $observed_dec;
    @cmd_result=&execute_command($miriad_command);
    my $next_line=0;
    for (my $i=0;$i<=$#cmd_result;$i++){
	if ($next_line==1){
	    my @els=split(/\s+/,$cmd_result[$i]);
	    $observed_ra=$els[2];
	    $observed_dec=$els[3];
	    $next_line=0;
	} elsif ($cmd_result[$i]=~/^\sSource/){
	    $next_line=1;
	}
    }
    
    return($observed_ra,$observed_dec);
}

sub calibrate_source {
    my ($path,$source,$freq,$bpflag)=@_;
    my $miriad_command;

    $path=&shrink_path($path);
    # start with an mfcal
    $miriad_command="mfcal ";
    $miriad_command.="vis=".$path."/".$source.".".$freq." ";
    $miriad_command.="interval=0.1";
    if ($bpflag==0){
	# this is not the bandpass calibrator
	$miriad_command.=" options=nopassol";
    }
    
    &execute_command($miriad_command);

#    # then a gpcal
#    $miriad_command="gpcal ";
#    $miriad_command.="vis=".$path."/".$source.".".$freq." ";
#    $miriad_command.="interval=0.1";
    
#    &execute_command($miriad_command);
}

sub calibration_copy {
    my ($in_path,$in_source,$in_freq,$out_path,$out_source,$out_freq)=@_;
    my $miriad_command;

    $in_path=&shrink_path($in_path);
    $out_path=&shrink_path($out_path);
    $miriad_command="gpcopy ";
    $miriad_command.="vis=".$in_path."/".$in_source.
	".".$in_freq." ";
    $miriad_command.="out=".$out_path."/".$out_source.".".
	$out_freq;

    &execute_command($miriad_command);
    
}
